<template>
  <div class="container" style="padding: 0px">
    <el-form :model="pageDto" ref="queryForm"  :inline="true" v-show="showSearch" label-width="68px">
      <slot v-bind="pageDto" name="pre-exactS earchForm">
        <!--        额外的搜索条件项-->
      </slot>
      <el-form-item v-for="(column,index) in searchformList" :key="index"  :prop="column.index">
        <template #label>
          <CustomTooltip :content="column.label" :width="68"></CustomTooltip>
        </template>
        <!--        如果是字典类型-->
        <template v-if="column.type=='dict'">
          <el-select v-model="pageDto[column.index]"
                     :placeholder="'请选择'+column.label"
                     clearable>
            <el-option
                v-for="dict in dict(column.dictkey)"
                :key="dict.value"
                :label="dict.label"
                :value="toStrOrInt(pageDto[column.index],dict.value)"
            />
          </el-select>
        </template>
        <template v-else>
          <el-input
              v-model="pageDto[column.index]"
              :type="column.dataType?column.dataType:'text'"
              :placeholder="'请输入'+column.label"
              clearable
              @keyup.enter.native="handleQuery"
          />
        </template>

      </el-form-item>
      <slot name="exactSearchForm" v-bind="pageDto">
        <!--        额外的搜索条件项-->
      </slot>
      <el-form-item>
        <el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
        <el-button icon="RefreshRight" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-row :gutter="10" style="margin-bottom: 8px;">
      <slot name="pre-exactToolbtn">
        <!--        额外的工具栏操作按钮-->
      </slot>
      <el-col :span="1.5" v-show="toolbar.indexOf('add')!=-1">
        <slot name="add">
          <el-button
              type="primary"
              plain
              icon="CirclePlusFilled"
              @click=" ()=>{saveVisible = true;form=reactive({})}"
          >新增
          </el-button>
        </slot>
      </el-col>
      <el-col :span="1.5" v-show="toolbar.indexOf('del')!=-1">
        <slot name="del" :del="multipleSelection">
          <el-button
              type="danger"
              plain
              icon="delete"
              @click="delAllSelection"
          >删除
          </el-button>
        </slot>
      </el-col>
      <el-col :span="1.5" v-show="toolbar.indexOf('upload')!=-1">
        <slot name="upload">
          <el-button
              type="info"
              plain
              @click="handleImport()"
              icon="upload"
          >导入
          </el-button>
        </slot>
      </el-col>
      <el-col :span="1.5" v-show="toolbar.indexOf('download')!=-1">
        <slot name="download">
          <el-button
              type="warning"
              plain
              @click="handleExport()"
              icon="download"
          >导出
          </el-button>
        </slot>
      </el-col>
      <slot name="exactToolbtn">
        <!--        额外的工具栏操作按钮-->
      </slot>
      <right-toolbar v-model:showSearch="showSearch" v-show="props.rightToolbar" @queryTable="readyGetData"
                     v-model:columns="showcoulumns" @updatcolumns="updatcolumns"></right-toolbar>
    </el-row>
    <el-table
        :data="tableData"
        class="table"
        ref="multipleTable"
        v-loading="listLoading"
        header-cell-class-name="table-header"
        @selection-change="handleSelectionChange"
    >
      <template slot="empty">
        <el-empty description="暂无数据"></el-empty>
      </template>
      <el-table-column type="selection" width="55" align="center"></el-table-column>
      <template v-for="(column,index) in columns" :key="index">
        <el-table-column :prop="column.index" :width="column.hasOwnProperty('width')?column.width:''"
                         v-if="column.visible||!column.hasOwnProperty('visible')"
                         :label="column.label" align="center">
          <template v-slot="scope" v-if="column.type!='opt'">
            <slot v-bind="scope" :name="column.index">
              <template v-if="column.type!='dict'">
                {{ scope.row[column.index] }}
              </template>
              <template v-else-if="dict(column.dictkey)">
                <dict-tag :key="index" :options="dict(column.dictkey)" :value="scope.row[column.index]"/>
              </template>
            </slot>
          </template>
          <template v-slot="scope" v-else>
            <slot :name="column.index" v-bind="scope">
              <el-button
                  type="primary"
                  link
                  icon="el-icon-edit"
                  @click="handleEdit(scope.$index, scope.row)"
              >编辑
              </el-button>
            </slot>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div class="pagination">
      <el-pagination
          background
          :page-sizes="[4, 7, 9, 10]"
          layout="total, sizes, prev, pager, next, jumper"
          :current-page="pageDto.page"
          :page-size="pageDto.size"
          :total="pageTotal"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      ></el-pagination>
    </div>
    <slot name="editformdialog">
      <!-- 编辑弹出框 -->
      <el-dialog title="编辑" v-model="editVisible" :before-close="function (){editVisible=false}" width="50%"
                 destroy-on-close>
        <el-form ref="editform" :model="form" label-width="70px">
          <el-form-item v-for="(columns,index) in editcoulumns" :key="index"
                        :rules="columns.rules" :prop="columns.index">
            <template #label>
              <CustomTooltip :content="columns.label" :width="70"></CustomTooltip>
            </template>
            <template v-if="columns.type=='dict'">
              <el-select v-model="form[columns.index]"
                         :placeholder="'请选择'+columns.label"
                         :disabled="columns['upd-disabled']"
                         clearable>
                <el-option
                    v-for="dict in dict(columns.dictkey)"
                    :key="dict.value"
                    :label="dict.label"
                    :value="toStrOrInt(form[columns.index],dict.value)"
                />
              </el-select>
            </template>
            <template v-else>
              <el-input :type="columns.dataType?columns.dataType:'text'" v-model="form[columns.index]"
                        :disabled="columns['upd-disabled']"></el-input>
            </template>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="editVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveEdit(editform)">确 定</el-button>
        </template>
      </el-dialog>
    </slot>
    <slot name="addformdialog">
      <!-- 新增弹出框 -->
      <el-dialog title="新增" v-model="saveVisible" :before-close="function (){saveVisible=false}" width="50%"
                 destroy-on-close>
        <el-form ref="addform" :model="form" label-width="70px">
          <el-form-item v-for="(columns,index) in addcoulumns" :key="index"
                        :rules="columns.rules" :prop="columns.index">
            <template #label>
              <CustomTooltip :content="columns.label" :width="70"></CustomTooltip>
<!--            <div class="label-container">-->
<!--              <span class="label-content" :title="columns.label">{{columns.label}}</span>-->
<!--            </div>-->
            </template>

            <template v-if="columns.type=='dict'">
              <el-select v-model="form[columns.index]" :disabled="columns['add-disabled']"
                         :placeholder="'请选择'+columns.label"
                         clearable>
                <el-option
                    v-for="dict in dict(columns.dictkey)"
                    :key="dict.value"
                    :label="dict.label"
                    :value="toStrOrInt(form[columns.index],dict.value)"
                />
              </el-select>
            </template>
            <template v-else>
              <el-input :type="columns.dataType?columns.dataType:'text'"
                        v-model="form[columns.index]"
                        :disabled="columns['add-disabled']"></el-input>
            </template>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="saveVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveEdit(addform)">确 定</el-button>
        </template>
      </el-dialog>
    </slot>
    <slot name="uploadformdialog">
      <!-- 用户导入对话框 -->
      <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
        <el-upload
            ref="uploadfile"
            :limit="1"
            accept=".xlsx, .xls"
            :headers="upload.headers"
            :action="upload.url"
            :disabled="upload.isUploading"
            :on-progress="handleFileUploadProgress"
            :on-success="handleFileSuccess"
            :auto-upload="false"
            drag
        >
          <template v-slot:trigger>
            <el-icon class="el-icon--upload">
              <upload-filled/>
            </el-icon>
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
          </template>
          <div class="el-upload__tip text-center" slot="tip">
            <div class="el-upload__tip" slot="tip">
              <el-checkbox v-model="upload.updateSupport"/>
              是否更新已经存在的用户数据
            </div>
            <span>仅允许导入xls、xlsx格式文件。</span>
            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
                     @click="importTemplate">下载模板
            </el-link>
          </div>
        </el-upload>
        <template #footer>
          <el-button type="primary" @click="submitFileForm">确 定</el-button>
          <el-button @click="upload.open = false">取 消</el-button>
        </template>
      </el-dialog>
    </slot>
  </div>
</template>

<script lang="ts" setup>
import {
  defineProps,
  defineEmits,
  defineExpose,
  ref,
  inject,
  reactive,
  onMounted,
  getCurrentInstance,
  watch,
  computed, ComponentInternalInstance, toRaw
} from 'vue'
import {ElMessage, ElMessageBox, FormInstance} from "element-plus";
import {deteleAllData, deteleData, ExportData, fetchData, saveorUpadateDate} from "@/api";
import {useStore} from "vuex";
import {LoadDict} from "@/utils/dict";

const {proxy} = getCurrentInstance() as ComponentInternalInstance
const props = defineProps({
  tabletype: {
    type: String,
    default: "normal"
  },
  item: {
    type: Object,
    default: {
      "type": "column",//普通行，字典行，自定义行
      "dictkey": "",//字典key值
      "lable": "",//标签名称
      "index": "",//数据库索引
      "rules": "",//值规则
      "search": "true",//是否是搜索表单
      "visible": "true",//默认可见,
      "dataType": "",//值值类型默认字符类型
      "value": "",//自定义值类型,
      "addable": "true",
      "editable": "true",
      "width": "auto",//宽度
      "add-disabled": "false",
      "upd-disabled": "false"

    }
  },
  toolbar: {
    type: Array,
    default: ["add", "del", "upload", "download"]
  },
  listapiurl: {
    type: String,
    default: "list"
  },
  updapiurl: {
    type: String,
    default: "save"
  },
  exportapiurl: {
    type: String,
    default: "export"
  },
  delapiurl: {
    type: String,
    default: "del"
  },
  exportTemplateapiurl: {
    type: String,
    default: "exportTemplate"
  },
  uploadExcelapiurl: {
    type: String,
    default: "uploadExcel"
  },
  columns: {
    type: Array,
  },
  id: {
    type: String,
    default: "id"
  },
  url: {
    type: String, //数据请求地址根路径
    default: "/process/admin/"
  },
  tableName: {  //表名
    type: String,
    default: "",
  },
  rightToolbar: {
    type: Boolean,
    default: true
  },
  queryDataSelf: {
    type: Boolean,
    default: false,
  },
  saveDataSelf: {
    type: Boolean,
    default: false,
  },
  delDataSelf: {
    type: Boolean,
    default: false,
  },


})
let Tool = inject("$Tool")
const store = useStore();
let internalInstance = getCurrentInstance()
let tableData = ref([])
let multipleSelection = ref([])
let delList = reactive([])
let editVisible = ref(false)
let saveVisible = ref(false)
let pageTotal = ref(0)
let showSearch = ref(true)
let listLoading = ref(false)
let form = reactive({})
let searchformList = reactive([])
let showcoulumns = reactive([])
let addcoulumns = reactive([])
let editcoulumns = reactive([])
let idx = ref(-1)
let id = ref(-1)
const pageDto = reactive({
  current: 1,
  size: 10
})
const emit = defineEmits(["update:columns","update:selectValues","queryDataFunction","saveDataFunction","delDataFunction"]);
const upload = reactive({
  // 是否显示弹出层（用户导入）
  open: false,
  // 弹出层标题（用户导入）
  title: "",
  // 是否禁用上传
  isUploading: false,
  // 是否更新已经存在的用户数据
  updateSupport: 0,
  // 设置上传的请求头部
  headers: {Authorization: `Bearer ${Tool.getLoginUser().token}`},
  // 上传的地址
  url: props.url + "/" + props.tableName + `/${props.uploadExcelapiurl}`
})
let uploadfile = ref<FormInstance>()
let editform = ref<FormInstance>();
let addform = ref<FormInstance>();
let queryForm = ref<FormInstance>();
let getData = () => {
  listLoading.value = true
  fetchData(props.url + "/" + props.tableName + `/${props.listapiurl}`, pageDto).then((res: any) => {
    listLoading.value = false
    tableData.value = res.records;
    pageTotal.value = res.total;
  }).finally(() => {
    listLoading.value = false
  });
}
let readyGetData = async () => {
  if (props.queryDataSelf) {
    emit('queryDataFunction',pageDto,(res)=>{
      tableData.value = res.records;
      pageTotal.value = res.total;
    })
  } else {
    getData()
  }
}



onMounted(async () => {
  let dicts = [];
  for (let columnsKey in props.columns) {
    let item: any = props.columns[columnsKey]
    if (item.type != 'opt') {
      if (item.search) {
        searchformList.push(item);
      }
      if (item.type == 'dict') {
        dicts.push(item.dictkey)
      }
      showcoulumns.push(item)
      if (!item.hasOwnProperty("addable") || item.addable) {
        addcoulumns.push(item)
      }
      if (!item.hasOwnProperty("editable") || item.editable) {
        editcoulumns.push(item)
      }
    }
  }
  LoadDict(dicts);
  readyGetData()
})
const dict = computed(() => {
  return function (key: any) {
    var dicts = store.state.dicts.dictMap.get(key);
    if (dicts) {
      return toRaw(dicts.type[key])
    } else {
      return []
    }
  }
})
const toStrOrInt=((formdata:any,item:any)=>{
  return (typeof formdata==='string')?item:parseInt(item)
})
const updatcolumns = (changecoulumns) => {
  for (let i = 0; i < changecoulumns.length; i++) {
    for (let j = 0; j < props.columns.length; j++) {
      if (changecoulumns[i]["index"] == props.columns[j]["index"]) {
        props.columns[j]["visible"] = changecoulumns[i]["visible"]
      }
    }
  }
  internalInstance.ctx.$forceUpdate()
};


let handleSizeChange = (size: any) => {
  pageDto.size = size;
  readyGetData()
}
let handleCurrentChange = (page: any) => {
  pageDto.current = page;
  readyGetData()
}
let handleDelete = (index, row) => {
  // 二次确认删除
  ElMessageBox.confirm('确定要删除吗？', '提示', {
    type: 'warning'
  }).then(() => {
    let id = row.id
    deteleData(props.url + "/" + props.tableName + `/${props.delapiurl}/` + id).then(res => {
      ElMessage.success("删除成功")
      readyGetData()
    })
  }).catch(() => {
  });
}
let handleSelectionChange = (val: any) => {
  multipleSelection.value = val;
}
let delAllSelection = () => {
  const length = multipleSelection.value.length;
  let ids = [];
  delList = delList.concat(multipleSelection);
  for (let i = 0; i < length; i++) {
    ids.push(multipleSelection.value[i][props.id]);
  }
  if (ids.length != 0) {
    deteleAllData(props.url + "/" + props.tableName + `/${props.delapiurl}`, ids).then(res => {
      ElMessage.success("删除成功")
      readyGetData()
    })
  } else {
    ElMessage.warning("请选择要删除的记录！")
    return false;
  }
  multipleSelection.value = [];
}

let handleEdit = (index: any, row: any) => {
  idx.value = index;
  form = row;
  editVisible.value = true;
}
let saveEdit = (formName: FormInstance) => {
  formName.validate((valid) => {
    if (valid) {
      saveorUpadateDate(props.url + "/" + props.tableName + `/${props.updapiurl}`, form).then(res => {
        ElMessage.success("保存成功")
        readyGetData()
        saveVisible.value = false
        editVisible.value = false
        form = reactive({})
      });
    } else {
      return false;
    }
  })
}

let handleExport = () => {
  ExportData(props.url + "/" + props.tableName + `/${props.exportapiurl}`).then(res => {
    Tool.downloadFile(res)
  })
}
/** 导入按钮操作 */
let handleImport = () => {
  upload.title = "导入";
  upload.open = true;
}
/** 下载模板操作 */
let importTemplate = () => {
  ExportData(props.url + "/" + props.tableName + `/${props.exportTemplateapiurl}`).then(res => {
    Tool.downloadFile(res)
  })
}
let submitFileForm = () => {
  uploadfile.submit();
}
let handleFileUploadProgress = (event, file: any, fileList: any) => {
  upload.isUploading = true;
}
let handleFileSuccess = (response: any, file: any, fileList: any) => {
  upload.open = false;
  upload.isUploading = false;
  uploadfile.clearFiles();
  ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", {dangerouslyUseHTMLString: true});
  readyGetData()
}
let handleQuery = () => {
  pageDto.current = 1;
  readyGetData()
}
/** 重置按钮操作 */
let resetForm = (formName: FormInstance | undefined) => {
  if (formName !== undefined) {
    formName.resetFields()
  }
}
/** 重置按钮操作 */
let resetQuery = () => {
  {
    resetForm(queryForm.value);
    handleQuery();
  }
}
let updform = (value: any) => {
  form = reactive(value)
}
defineExpose({
  readyGetData,
  handleEdit,
  saveEdit,
  delAllSelection,
  handleDelete,
  dict,
  form,
  updform,
  editVisible,
  saveVisible

})


</script>
<style lang="scss">
.handle-box {
  margin-bottom: 20px;
}

.table {
  width: 100%;
  font-size: 14px;
}

.red {
  color: #ff0000;
}

.hidecolumns {
  display: none;
}

.mr10 {
  margin-right: 10px;
}




</style>